// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
import 'chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js';
import 'chrome://resources/cr_elements/shared_vars_css.m.js';
import 'chrome://resources/cr_elements/shared_style_css.m.js';
import 'chrome://resources/cr_components/customize_themes/customize_themes.js';
import './shared_css.js';
import '../icons.js';
import '../profile_picker_shared_css.js';

import {Theme, ThemeInfo, ThemeType} from 'chrome://resources/cr_components/customize_themes/customize_themes.mojom-webui.js';
import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
import {AvatarIcon} from 'chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js';
import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js';
import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';

import {AutogeneratedThemeColorInfo, ManageProfilesBrowserProxy, ManageProfilesBrowserProxyImpl, UserThemeChoice} from '../manage_profiles_browser_proxy.js';
import {navigateTo, navigateToPreviousRoute, Routes} from '../navigation_mixin.js';
import {isProfileCreationAllowed} from '../policy_helper.js';

export interface LocalProfileCustomizationElement {
  $: {
    backButton: HTMLElement,
    doneButton: CrButtonElement,
    nameInput: CrInputElement,
    save: CrButtonElement,
    selectAvatarDialog: CrDialogElement,
    wrapperContainer: HTMLElement,
    wrapper: HTMLElement,
  };
}

const LocalProfileCustomizationElementBase =
    WebUIListenerMixin(I18nMixin(PolymerElement));

export class LocalProfileCustomizationElement extends
    LocalProfileCustomizationElementBase {
  static get is() {
    return 'local-profile-customization';
  }

  static get template() {
    return html`{__html_template__}`;
  }

  static get properties() {
    return {
      /**
       * The theme info used to display colored UI elements.
       */
      profileThemeInfo: {
        type: Object,
        observer: 'onProfileThemeInfoChange_',
        notify: true,
      },

      /**
       * The currently selected theme in the color picker.
       */
      selectedTheme_: {
        type: Object,
        observer: 'onSelectedThemeChange_',
      },

      /**
       * True if `selectedTheme_` doesn't need to be updated when
       * `profileThemeInfo` changes.
       */
      disableSelectedThemeUpdates_: {
        type: Boolean,
        value: false,
      },

      /**
       * Colored default generic avatar in the format expected by
       * 'cr-profile-avatar-selector'
       */
      genericDefaultAvatar_: {
        type: Object,
        computed:
            'getGenericDefaultAvatar_(profileThemeInfo.themeGenericAvatar)',
        observer: 'onGenericDefaultAvatarChange_',
      },

      /**
       * List of available profile icon Urls and labels.
       */
      availableIcons_: {
        type: Array,
        value() {
          return [];
        },
      },

      /**
       * The currently selected profile avatar, if any.
       */
      selectedAvatar_: Object,

      /**
       * The current profile name.
       */
      profileName_: {
        type: String,
        value: '',
      },

      /**
       * if true, a desktop shortcut will be created for the new profile.
       */
      createShortcut_: {
        type: Boolean,
        value: true,
      },

      /**
       * True if the profile shortcuts feature is enabled.
       */
      isProfileShortcutsEnabled_: {
        type: Boolean,
        value: () => loadTimeData.getBoolean('profileShortcutsEnabled'),
      },

      /**
       * True if a profile is being created or imported.
       */
      createInProgress_: {
        type: Boolean,
        value: false,
      },

      pattern_: {
        type: String,
        value: '.*\\S.*',
      },

      defaultAvatarIndex_: {
        type: Number,
        value: () => loadTimeData.getInteger('placeholderAvatarIndex'),
      },
    };
  }

  profileThemeInfo: AutogeneratedThemeColorInfo;
  private selectedTheme_: Theme;
  private disableSelectedThemeUpdates_: boolean;
  private genericDefaultAvatar_: AvatarIcon;
  private availableIcons_: Array<AvatarIcon>;
  private selectedAvatar_: AvatarIcon|null;
  private profileName_: string;
  private createShortcut_: boolean;
  private isProfileShortcutsEnabled_: boolean;
  private createInProgress_: boolean;
  private pattern_: string;
  private defaultAvatarIndex_: number;
  private manageProfilesBrowserProxy_: ManageProfilesBrowserProxy =
      ManageProfilesBrowserProxyImpl.getInstance();
  private resizeObserver_: ResizeObserver|null = null;

  ready() {
    super.ready();
    this.sanityCheck_();
    this.addWebUIListener(
        'create-profile-finished', () => this.handleCreateProfileFinished_());
    this.manageProfilesBrowserProxy_.getAvailableIcons().then(
        icons => this.setAvailableIcons_(icons));

    this.addEventListener('view-enter-start', this.onViewEnterStart_);
  }

  connectedCallback() {
    super.connectedCallback();
    this.addResizeObserver_();
  }

  disconnectedCallback() {
    super.disconnectedCallback();
    this.resizeObserver_!.disconnect();
  }

  private addResizeObserver_() {
    const wrapperContainer = this.$.wrapperContainer;
    this.resizeObserver_ = new ResizeObserver(() => {
      this.shadowRoot!.querySelector('.footer')!.classList.toggle(
          'division-line',
          wrapperContainer.scrollHeight > wrapperContainer.clientHeight);
    });
    this.resizeObserver_.observe(wrapperContainer);
  }

  private onViewEnterStart_() {
    if (this.profileName_.length === 0) {
      this.$.nameInput.invalid = false;
    }
    this.$.nameInput.focusInput();
    this.$.wrapper.scrollTop = 0;
  }

  private getBackButtonAriaLabel_(): string {
    return this.i18n(
        'backButtonAriaLabel', this.i18n('localProfileCreationTitle'));
  }

  private sanityCheck_(): boolean {
    if (!isProfileCreationAllowed()) {
      this.onBackClick_();
      return false;
    }
    return true;
  }

  /**
   * Handler for profile name blur.
   */
  private onProfileNameInputBlur_() {
    this.$.nameInput.validate();
  }

  /**
   * Determining whether 'Save' button is disabled.
   */
  private isSaveDisabled_(): boolean {
    return this.createInProgress_ || !this.profileName_ ||
        !this.$.nameInput.validate();
  }

  /**
   * Handler for the 'Save' button click event.
   */
  private onSaveClick_() {
    if (!this.sanityCheck_()) {
      return;
    }

    if (this.createInProgress_) {
      return;
    }
    this.createInProgress_ = true;
    const createShortcut =
        this.isProfileShortcutsEnabled_ && this.createShortcut_;
    this.manageProfilesBrowserProxy_.createProfile(
        this.profileName_, this.profileThemeInfo.color,
        this.selectedAvatar_!.index, createShortcut);
  }

  private onBackClick_() {
    navigateToPreviousRoute();
  }

  private onCustomizeAvatarClick_() {
    this.$.selectAvatarDialog.showModal();
  }

  private onDoneSelectAvatarClick_() {
    this.$.selectAvatarDialog.close();
  }

  private getGenericDefaultAvatar_(): AvatarIcon {
    return {
      url: this.profileThemeInfo.themeGenericAvatar,
      label: this.i18n('defaultAvatarLabel'),
      index: this.defaultAvatarIndex_,
      isGaiaAvatar: false,
      selected: false,
    };
  }

  private onGenericDefaultAvatarChange_() {
    this.setAvailableIcons_([...this.availableIcons_]);
    if (!this.selectedAvatar_ ||
        this.selectedAvatar_.index === this.defaultAvatarIndex_) {
      this.selectedAvatar_ = this.genericDefaultAvatar_;
    }
  }

  private setAvailableIcons_(icons: Array<AvatarIcon>) {
    if (!this.genericDefaultAvatar_) {
      this.availableIcons_ = icons;
      return;
    }
    const offset =
        icons.length > 0 && icons[0].index === this.defaultAvatarIndex_ ? 1 : 0;
    this.availableIcons_ = [this.genericDefaultAvatar_, ...icons.slice(offset)];
  }

  private onProfileThemeInfoChange_() {
    if (this.disableSelectedThemeUpdates_) {
      return;
    }

    this.selectedTheme_ = {
      type: ThemeType.kChrome,
      info: {
        chromeThemeId: this.profileThemeInfo.colorId,
      } as ThemeInfo,
      isForced: false,
    };
  }

  private async onSelectedThemeChange_() {
    let theme: UserThemeChoice|null = null;
    if (this.selectedTheme_.type === ThemeType.kAutogenerated) {
      theme = {
        colorId: 0,
        color: this.selectedTheme_.info.autogeneratedThemeColors!.frame.value
      };
    } else if (this.selectedTheme_.type === ThemeType.kChrome) {
      theme = {
        colorId: this.selectedTheme_.info.chromeThemeId!,
      };
    } else if (this.selectedTheme_.type === ThemeType.kDefault) {
      theme = {
        colorId: -1,
      };
    }

    const newThemeInfo =
        await this.manageProfilesBrowserProxy_.getProfileThemeInfo(theme!);
    this.disableSelectedThemeUpdates_ = true;
    this.profileThemeInfo = newThemeInfo;
    this.disableSelectedThemeUpdates_ = false;
  }

  private handleCreateProfileFinished_() {
    // On profile creation, the picker window is closed.
    // 'navigateTo' is meaningful if the picker is shown in a tab.
    navigateTo(Routes.MAIN);
    this.createInProgress_ = false;
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'local-profile-customization': LocalProfileCustomizationElement;
  }
}

customElements.define(
    LocalProfileCustomizationElement.is, LocalProfileCustomizationElement);
